﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.AddressableAssets;
using SangsTools;

namespace Battle
{
    public class PowerGridMgr : MonoBehaviour
    {
        private const string TexturePath = "PowerGridTexture";
        private const float LineWidth = 5;
        private const float RefreshInterval = 0.2f,AttackInterval=0.2f;

        private static PowerGridMgr _ins;
        public static PowerGridMgr Ins
        {
            get
            {
                if (_ins == null)
                {
                    _ins = new GameObject("PowerGridMgr").AddComponent<PowerGridMgr>();
                    DontDestroyOnLoad(_ins.gameObject);
                }
                return _ins;
            }
        }

        private Texture texture;

        [SerializeField]
        public List<Bullet_PowerPoint> listPoint { get; private set; } = new List<Bullet_PowerPoint>();
        protected List<(Bullet_PowerPoint one, Bullet_PowerPoint other)> listLine=new List<(Bullet_PowerPoint one, Bullet_PowerPoint other)>();

        private async void Awake()
        {

            texture= await Addressables.LoadAssetAsync<Texture>(TexturePath).Task;
            RefreshLineAsync();
            UpdataAttakAsync();
        }

        private void OnGUI()
        {
            if (texture == null || listLine == null) return;

            for (int i = 0; i < listLine.Count; i++)
            {
                if (listLine[i].one == null || listLine[i].other == null) continue;
                if (CheckOut(listLine[i].one.Pos) || CheckOut(listLine[i].other.Pos)) continue;

                GUI_Tools.GUI_DrawLine_World(listLine[i].one.transform.position, listLine[i].other.transform.position,
                    LineWidth, texture);
            }
        }

        private async void RefreshLineAsync()
        {
            while (Application.isPlaying && gameObject != null)
            {
                listLine.Clear();
                for (int i = 0; i < listPoint.Count; i++)
                {
                    for (int j = i + 1; j < listPoint.Count; j++)
                    {
                        if (CheckCanConnect(listPoint[i], listPoint[j]))
                            listLine.Add((listPoint[i], listPoint[j]));
                    }
                }

                await Task.Delay((int)(RefreshInterval * 1000));
            }
        }
        private async void UpdataAttakAsync()
        {
            while (Application.isPlaying && gameObject != null)
            {
                Attack();

                await Task.Delay((int)(AttackInterval * 1000));
            }
        }

        private void Attack()
        {
            //防止被多次伤害
            List<Collider2D> tmpList = new List<Collider2D>();

            for (int i = 0; i < listLine.Count; i++)
            {
                if (listLine[i].one == null || listLine[i].other == null) continue;
                if (CheckOut(listLine[i].one.Pos) || CheckOut(listLine[i].other.Pos)) continue;

                Vector3 dir = listLine[i].other.Pos - listLine[i].one.Pos;
                var arrHitInfo = Physics2D.RaycastAll(listLine[i].one.Pos, dir.normalized, dir.magnitude);

                if (arrHitInfo != null)
                {
                    int dmg = (listLine[i].one.BulletData.nDmg + listLine[i].other.BulletData.nDmg) / 2;
                    int repelNum= (listLine[i].one.BulletData.nRepelNum + listLine[i].other.BulletData.nRepelNum) / 2;
                    for (int j = 0; j < arrHitInfo.Length; j++)
                    {
                        if (tmpList.Contains(arrHitInfo[j].collider)) continue;
                        tmpList.Add(arrHitInfo[j].collider);

                        ICanHitObj canHitObj = arrHitInfo[j].collider.GetComponentInParent<ICanHitObj>();

                        if (canHitObj != null)
                        {
                            HitObj(canHitObj,dmg,repelNum);
                        }
                    }
                }
            }
        }

        private void HitObj(ICanHitObj canHitObj,int dmg, int repelNum)
        {
            canHitObj?.OnHit(new ST_HitActionData()
            {
                fAtk=dmg,
                nRepelNum=repelNum,
            });
        }

        private bool CheckCanConnect(Bullet_PowerPoint one,Bullet_PowerPoint other)
        {
            return (one.transform.position - other.transform.position).sqrMagnitude <= 
                Mathf.Pow((float)(one.BulletData.rangeData.dRadius + other.BulletData.rangeData.dRadius) , 2);
        }

        private bool CheckOut(Vector3 pos)
        {
            return pos.y > GameMgr.ScreenSize.y ;
            //return pos.y > GameMgr.ScreenSize.y || Mathf.Abs(pos.x) > GameMgr.ScreenSize.x;
        }
    }
}
